Public Class ParallelComms


  Private Structure DCB
    Public DCBlength As Int32
    Public BaudRate As Int32
    Public fBitFields As Int32 'See Comments in Win32API.Txt
    Public wReserved As Int16
    Public XonLim As Int16
    Public XoffLim As Int16
    Public ByteSize As Byte
    Public Parity As Byte
    Public StopBits As Byte
    Public XonChar As Byte
    Public XoffChar As Byte
    Public ErrorChar As Byte
    Public EofChar As Byte
    Public EvtChar As Byte
    Public wReserved1 As Int16 'Reserved; Do Not Use
  End Structure


  Private Structure COMMTIMEOUTS
    Public ReadIntervalTimeout As Int32
    Public ReadTotalTimeoutMultiplier As Int32
    Public ReadTotalTimeoutConstant As Int32
    Public WriteTotalTimeoutMultiplier As Int32
    Public WriteTotalTimeoutConstant As Int32
  End Structure

  Private Const GENERIC_READ As Int32 = &H80000000
  Private Const GENERIC_WRITE As Int32 = &H40000000
  Private Const OPEN_EXISTING As Int32 = 3
  Private Const FILE_ATTRIBUTE_NORMAL As Int32 = &H80
  Private Const NOPARITY As Int32 = 0
  Private Const ONESTOPBIT As Int32 = 0

  Private Structure SECURITY_ATTRIBUTES
    Public nLength As Integer
    Public lpSecurityDescriptor As Integer
    Public bInheritHandle As Integer
  End Structure

  Private Const INVALID_HANDLE_VALUE = -1

  Private Structure OVERLAPPED
    Public Internal As Integer
    Public InternalHigh As Integer
    Public offset As Integer
    Public OffsetHigh As Integer
    Public hEvent As Integer
  End Structure

  Private Declare Auto Function CreateFile Lib "kernel32.dll" (ByVal lpFileName As String, ByVal dwDesiredAccess As Int32, ByVal dwShareMode As Int32, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As Int32, ByVal dwFlagsAndAttributes As Int32, ByVal hTemplateFile As IntPtr) As IntPtr
  Private Declare Auto Function GetCommState Lib "kernel32.dll" (ByVal nCid As IntPtr, ByRef lpDCB As DCB) As Boolean
  Private Declare Auto Function SetCommState Lib "kernel32.dll" (ByVal nCid As IntPtr, ByRef lpDCB As DCB) As Boolean
  Private Declare Auto Function GetCommTimeouts Lib "kernel32.dll" (ByVal hFile As IntPtr, ByRef lpCommTimeouts As COMMTIMEOUTS) As Boolean
  Private Declare Auto Function SetCommTimeouts Lib "kernel32.dll" (ByVal hFile As IntPtr, ByRef lpCommTimeouts As COMMTIMEOUTS) As Boolean
  Private Declare Auto Function WriteFile Lib "kernel32.dll" (ByVal hFile As IntPtr, ByVal lpBuffer As Byte(), ByVal nNumberOfBytesToWrite As Int32, ByRef lpNumberOfBytesWritten As Int32, ByVal lpOverlapped As IntPtr) As Boolean
  Private Declare Auto Function ReadFile Lib "kernel32.dll" (ByVal hFile As IntPtr, ByVal lpBuffer As Byte(), ByVal nNumberOfBytesToRead As Int32, ByRef lpNumberOfBytesRead As Int32, ByVal lpOverlapped As IntPtr) As Boolean
  Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal hObject As IntPtr) As Boolean


  Private portHandle As IntPtr

  Public Sub New()
    ' Class constructor
    portHandle = IntPtr.Zero
  End Sub

  Public Sub New(ByVal portName As String)
    ' Constructore that attempts to open a port automatically
    OpenParallelPort(portName)
  End Sub

  Protected Overrides Sub Finalize()
    ' Destructor, ensure that the port is closed
    If isOpen() Then CloseParallelPort()
    MyBase.Finalize()
  End Sub

  Public Function isOpen() As Boolean
    ' Return true if the port is open
    If portHandle.ToInt32() > 0 Then
      Return True
    Else
      Return False
    End If
  End Function

  Public Function OpenParallelPort(ByVal portname As String) As Boolean
    ' Open the indicated parallel port

    Dim secattr As SECURITY_ATTRIBUTES

    portHandle = CreateFile(portname, GENERIC_READ Or GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)

    If portHandle.ToInt32() = INVALID_HANDLE_VALUE Then
      Return False
    Else
      Return True
    End If
  End Function

  Public Function WriteParallelPort(ByVal data As String) As Integer
    ' Write data to the parallel port, return length of data written sucessfully

    Dim bytesWritten As Int32
    Dim check As Boolean

    ' Declare variables to use for encoding.
    Dim oEncoder As New System.Text.ASCIIEncoding
    Dim oEnc As System.Text.Encoding = oEncoder.GetEncoding(1252)

    Dim buffer() As Byte

    buffer = oEnc.GetBytes(data)

    ' ensure that the port is already open
    If Not isOpen() Then Return 0

    ' write data
    check = WriteFile(portHandle, buffer, data.Length(), bytesWritten, IntPtr.Zero)

    If Not check Then
      ' Failed completely (port may not have been opened
      Return 0
    Else
      Return bytesWritten
    End If

  End Function

  Public Function CloseParallelPort()
    ' Close the parallel port
    If isOpen() Then CloseHandle(portHandle)
  End Function

End Class
